﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NetDon.OA.Data.CollectionClasses;
using NetDon.OA.Data.EntityClasses;
using NetDon.OA.Data.HelperClasses;
using NetDon.OA.Data.Linq;
using NetDon.OA.Interface.Admin;
using SD.LLBLGen.Pro.ORMSupportClasses;

namespace NetDon.OA.Business.Admin
{
    public class DepartmentService : PrimitiveHierarchyService<DepartmentData>, IDepartmentService
    {
        public DepartmentService()
            : base("DepartmentData")
        {
        }
        #region IDepartmentService Members
        public DepartmentDataCollection GetChildDepartments(Guid departmentId)
        {
            return new DepartmentDataCollection(GetChildNodes(departmentId).OrderBy(i => i.DepartmentName).ToArray());
        }

        public DepartmentDataCollection GetRootDepartments(Guid companyId)
        {
            return new DepartmentDataCollection(GetChildNodes(companyId).OrderBy(i => i.DepartmentName).ToArray());
        }

        public DepartmentData GetDepartment(Guid departmentId)
        {
            return GetData(departmentId);
        }

        public bool RemoveDepartment(Guid departmentId)
        {
            return RemoveData(departmentId);
        }

        public bool CheckDepartmentUsed(Guid departmentId)
        {
            var department = GetDepartment(departmentId);
            if (department == null)
            {
                return false;
            }

            return new DepartmentCollection().GetDbCount(DepartmentFields.ParentDepartId == departmentId) > 0 ||

                 new UserCollection().GetDbCount(UserFields.DepartId == departmentId) > 0;
        }

        public bool AddDepartment(DepartmentData department)
        {
            return AddData(department);
        }

        public bool ModifyDepartment(DepartmentData department)
        {
            return ModifyData(department.DepartmentId, department);
        }
        #endregion

        #region PrimitiveHierarchyService
        protected virtual IEnumerable<DepartmentData> OnLoadRootNodes(Guid companyId, ITransaction transaction)
        {
            var meta = new LinqMetaData(transaction);
            var list = (from department in meta.Department
                        where department.CompanyId == companyId
                        select department).ToList();
            return list.Select(department => GetDepartmentData(department));
        }


        protected IEnumerable<DepartmentData> GetRootNodes(Guid companyId)
        {
            return GetRootNodes(companyId, null);
        }

        protected virtual IEnumerable<DepartmentData> GetRootNodes(Guid companyId, ITransaction transaction)
        {

            var keys = GetCache<ArrayList>(CacheKey);

            if (keys == null)
            {
                IEnumerable<DepartmentData> rootNodes = OnLoadRootNodes(companyId, transaction);
                if (rootNodes == null)
                {
                    SetCache(CacheKey, null);
                    return null;
                }
                keys = new ArrayList();
                foreach (DepartmentData data in rootNodes)
                {
                    object key = GetDataKey(data);
                    SetCache(GenerateCacheKey(key), data);
                    keys.Add(key);
                }
                SetCache(CacheKey, keys);
                return rootNodes;
            }
            var listData = new List<DepartmentData>();
            foreach (object key in keys)
            {
                listData.Add(GetData(key, transaction));
            }
            return listData;
        }

        #endregion


        #region Overrides of CachableServiceBase<CompanyData>

        protected override DepartmentData OnLoadData(object key, ITransaction transaction)
        {
            var meta = new LinqMetaData(transaction);
            List<DepartmentEntity> list = (from department in meta.Department
                                           where department.DepartId == (Guid)key
                                           select department).ToList();
            return list.Count > 0 ? GetDepartmentData(list[0]) : null;
        }

        protected override object GetDataKey(DepartmentData data)
        {
            return data.DepartmentId;
        }

        protected override bool OnRemoveData(object key, DepartmentData data, ITransaction transaction)
        {
            if (base.OnRemoveData(key, data, transaction))
            {
                var collection = new Data.CollectionClasses.DepartmentCollection();
                transaction.Add(collection);
                return collection.DeleteMulti(DepartmentFields.DepartId == (Guid)key) > 0;
            }
            return false;
        }

        protected override bool OnAddData(DepartmentData data, ITransaction transaction)
        {
            if (!ValidateDepartment(data, transaction))
            {
                return false;
            }
            string parentPath = data.ParentId.HasValue ? GetDepartment(data.ParentId.Value).Path : string.Empty;
            var childNodes = data.ParentId.HasValue ? GetChildNodes(data.ParentId.Value) : GetRootNodes();
            string path = parentPath + childNodes.Count().ToString("X").PadLeft(4, '0');
            var entity = new DepartmentEntity
            {
                DepartId = data.DepartmentId,
                ParentDepartId = data.ParentId,
                DepartCode = data.DepartmentCode,
                DepartName = data.DepartmentName,
                Address = data.Address,
                DepartDesc = data.DepartmentDesc,
                CompanyId = data.CompanyId,
                Fax = data.Fax,
                Telephone = data.Telephone,
                NodeLevel = data.NodeLevel,
                Manager = data.Manager
            };
            transaction.Add(entity);
            if (entity.Save())
            {
                data.DepartmentId = entity.DepartId;
                data.Path = path;
                return true;
            }
            return false;
        }

        protected override bool OnModifyData(object key, DepartmentData data, ITransaction transaction)
        {
            if (!ValidateDepartment(data, transaction))
            {
                return false;
            }
            var entity = new DepartmentEntity();
            transaction.Add(entity);
            entity.FetchUsingPK((Guid)key);
            if (entity.IsNew)
            {
                return false;
            }
            var path = GetDepartment((Guid)key).Path;
            entity.ParentDepartId = data.ParentId;
            entity.DepartCode = data.DepartmentCode;
            entity.DepartName = data.DepartmentName;
            entity.Address = data.Address;
            entity.DepartDesc = data.DepartmentDesc;
            entity.CompanyId = data.CompanyId;
            entity.Fax = data.Fax;
            entity.Telephone = data.Telephone;
            entity.NodeLevel = data.NodeLevel;
            entity.Manager = data.Manager;
            return entity.Save();
        }

        #endregion

        #region Overrides of HierarchyCachableService<CompanyData>

        protected override object GetParentKey(DepartmentData data)
        {
            return data.ParentId == null || data.ParentId == Guid.Empty ? data.CompanyId :
            data.ParentId;
        }

        protected override IEnumerable<DepartmentData> OnLoadChildNodes(object parentKey,
                                                                               ITransaction transaction)
        {
            var meta = new LinqMetaData(transaction);
            var list = (from department in meta.Department
                        where department.ParentDepartId == (Guid?)parentKey || (department.CompanyId == (Guid?)parentKey && (department.ParentDepartId == null || department.ParentDepartId == Guid.Empty))
                        select department).ToList();
            return list.Select(company => GetDepartmentData(company));
        }

        #endregion

        #region Overrides of PrimitiveHierarchyService<CompanyData>

        protected override IEnumerable<DepartmentData> OnLoadRootNodes(ITransaction transaction)
        {
            var meta = new LinqMetaData(transaction);
            var list = (from department in meta.Department
                        where department.ParentDepartId == null
                        select department).ToList();
            return list.Select(deparment => GetDepartmentData(deparment));
        }

        #endregion


        private DepartmentData GetDepartmentData(DepartmentEntity entity)
        {
            return new DepartmentData
                       {
                           ParentId = entity.ParentDepartId,
                           CompanyId = entity.CompanyId,
                           DepartmentCode = entity.DepartCode,
                           DepartmentName = entity.DepartName,
                           Address = entity.Address,
                           DepartmentDesc = entity.DepartDesc,
                           Fax = entity.Fax,
                           Telephone = entity.Telephone,
                           NodeLevel = entity.NodeLevel,
                           DepartmentId = entity.DepartId,
                           Manager = entity.Manager

                       };
        }

        private bool ValidateDepartment(DepartmentData data, ITransaction transaction)
        {
            var meta = new LinqMetaData(transaction);
            var list = (from department in meta.Department
                        where department.DepartCode == data.DepartmentCode && department.DepartId != data.DepartmentId && department.CompanyId ==data.CompanyId
                        select department).ToList();
            if (list.Count > 0)
            {
                data.SetError("DepartmentCode",
                             string.Format("相同的部门编号'{0}'已经存在。.", data.DepartmentCode));
                return false;
            }

            list = (from department in meta.Department
                    where department.DepartName == data.DepartmentName && department.DepartId != data.DepartmentId && department.CompanyId == data.CompanyId
                    select department).ToList();
            if (list.Count > 0)
            {
                data.SetError("DepartmentName",
                             string.Format("相同的部门名称'{0}'已经存在.", data.DepartmentName));
                return false;
            }
            //CompanyDataCollection companies = data.ParentId.HasValue
            //                                             ? GetChildCompanies(data.ParentId.Value)
            //                                             : GetRootCompanies();
            //if (companies != null &&
            //    companies.ToList().Find(
            //        company =>
            //        String.Compare(company.CompanyName, data.CompanyName, true) == 0 &&
            //        company.CompanyId != data.CompanyId) !=
            //    null)
            //{
            //    data.SetError("CompanyName",
            //                  string.Format("The company '{0}' has existed.", data.CompanyName));
            //    return false;
            //}
            return true;
        }




    }
}
